import type { AccountInfoSchema, PositionSchema } from "@/types/account.types";
import { ref } from "vue";
import { h, computed } from "vue";
import ProgressBar from "@/components/progress-bar/ProgressBar.vue";
import { usageRate } from "@/utils/math";
import { useBreakpointQuery } from "@/utils/device";
import { renderNumberCell, renderTextCell } from "@/utils/cell";

export const useAccountTable = () => {
  // Table definition
  const { isSmUp, isMdUp } = useBreakpointQuery();
  const tableSize = computed(() => {
    if (isSmUp()) {
      return "default";
    }
    return "small";
  });

  const getAccountColumns = () => {
    const isMediumUp = isMdUp();
    const isSmallUp = isSmUp();

    const useCompactLabels = !isSmallUp;

    const labelUsageRate = useCompactLabels ? "使用" : "使用率";
    const labelBalance = useCompactLabels ? "权益" : "最新权益";
    const labelMarketValue = useCompactLabels ? "市值" : "市值权益";
    const labelPnl = useCompactLabels ? "盈亏" : "持仓盈亏";
    const labelOptionValue = useCompactLabels ? "期权" : "期权市值";
    const labelTimeValue = useCompactLabels ? "时间" : "时间价值";
    const labelAvailable = useCompactLabels ? "可用" : "可用金额";
    const labelFrozen = useCompactLabels ? "冻结" : "冻结金额";

    const expandWidth = isMediumUp ? 48 : isSmallUp ? 30 : 20;
    const nameMinWidth = isMediumUp ? 150 : isSmallUp ? 130 : 105;
    const rateMinWidth = isMediumUp ? 150 : isSmallUp ? 100 : 80;
    const balanceMinWidth = isMediumUp ? 120 : isSmallUp ? 110 : 80;
    const numMinWidth = isMediumUp ? 100 : isSmallUp ? 85 : 80;

    const columns: TableColumnList = [
      {
        key: "expand",
        type: "expand",
        slot: "expand",
        width: expandWidth,
        className: "[&>div]:p-0!"
      },
      ...(isSmallUp
        ? [
            {
              key: "index",
              type: "index",
              label: "#",
              align: "center",
              width: 20,
              className: "text-[11px]! text-gray-400! [&>div]:p-0!"
            }
          ]
        : []),

      {
        key: "account_name",
        label: "账户名称",
        prop: "account_name",
        minWidth: nameMinWidth,
        align: "left",
        sortable: true,
        showOverflowTooltip: true,
        formatter: (row: AccountInfoSchema) => renderTextCell(row.account_name)
      },
      {
        key: "usageRate",
        label: labelUsageRate,
        prop: "usageRate",
        align: "center",
        minWidth: rateMinWidth,
        sortable: true,
        sortMethod: (a: AccountInfoSchema, b: AccountInfoSchema) =>
          usageRate(a.account.balance, a.account.available) -
          usageRate(b.account.balance, b.account.available),
        formatter: (row: AccountInfoSchema) =>
          h(ProgressBar, {
            percentage: Number(
              usageRate(row.account.balance, row.account.available)
            )
          })
      },
      {
        key: "account.balance",
        label: labelBalance,
        prop: "account.balance",
        align: "right",
        minWidth: balanceMinWidth,
        sortable: true,
        formatter: (row: AccountInfoSchema) =>
          renderNumberCell(row.account.balance, 0, false, false)
      },
      {
        key: "totalMarketValue",
        label: labelMarketValue,
        prop: "totalMarketValue",
        align: "right",
        minWidth: balanceMinWidth,
        sortable: true,
        formatter: (row: AccountInfoSchema) =>
          renderNumberCell(
            row.account.balance + row.totalMarketValue,
            0,
            false,
            false
          )
      },
      {
        key: "totalPnl",
        label: labelPnl,
        prop: "totalPnl",
        align: "right",
        minWidth: numMinWidth,
        formatter: (row: AccountInfoSchema) =>
          renderNumberCell(row.totalPnl as number, 0, false, true)
      },
      // 期权市值：在 xs 隐藏
      ...(isMediumUp
        ? [
            {
              key: "totalOptionMarketValue",
              label: labelOptionValue,
              prop: "totalOptionMarketValue",
              align: "right",
              minWidth: numMinWidth,
              formatter: (row: AccountInfoSchema) =>
                renderNumberCell(
                  row.totalOptionMarketValue as number,
                  0,
                  false,
                  true
                )
            } as any
          ]
        : []),
      // 时间价值：仅在 md 及以上展示
      ...(isMediumUp
        ? [
            {
              key: "totalOptionTimeValue",
              label: labelTimeValue,
              prop: "totalOptionTimeValue",
              align: "right",
              minWidth: numMinWidth,
              formatter: (row: AccountInfoSchema) =>
                renderNumberCell(
                  row.totalOptionTimeValue as number,
                  0,
                  false,
                  true
                )
            } as any
          ]
        : []),
      {
        key: "account.available",
        label: labelAvailable,
        prop: "account.available",
        minWidth: numMinWidth,
        align: "right",
        formatter: (row: AccountInfoSchema) =>
          renderNumberCell(row.account.available, 0, false, false)
      },
      ...(isMediumUp
        ? [
            {
              key: "account.frozen",
              label: labelFrozen,
              prop: "account.frozen",
              align: "right",
              minWidth: numMinWidth,
              formatter: (row: AccountInfoSchema) =>
                renderNumberCell(row.account.frozen, 0, false, false)
            } as any
          ]
        : [])
    ];

    return columns;
  };

  const accountColumns = computed(() => getAccountColumns());

  // Search and filter
  const accountSearch = ref<string>("");
  const symbolSearch = ref<string>("");

  /**
   * Filters account rows and their positions, orders, and trades using the current search terms.
   *
   * Rules and behavior:
   * - Trims both search strings before matching.
   * - Account filter: a row matches if `account_name` includes the account term (case-insensitive).
   * - Symbol filter: records match if their `symbol` includes the symbol term (case-insensitive).
   * - If both search terms are empty, returns the input array unchanged (fast path).
   * - If the symbol term is non-empty:
   *   - Positions are filtered to only those matching the symbol term.
   *   - Orders and trades are also filtered by symbol, but their presence does NOT affect whether a row is kept.
   *   - Accounts with zero positions after filtering are removed.
   * - If the symbol term is empty:
   *   - Positions, orders, and trades are preserved as-is.
   *   - Accounts are preserved even if they have no positions.
   *
   * Performance notes:
   * - Single pass over rows; when the symbol term is empty, rows are passed through without cloning.
   * - When the symbol term is present, `positions`, `orders`, and `trades` Maps are rebuilt with only matching records.
   *
   * @param data Array of `AccountInfoSchema` rows to filter.
   * @returns Filtered rows. When symbol search is active, rows are shallow-cloned with filtered `positions`, `orders`, and `trades` Maps.
   */
  const filterTableData = (data: AccountInfoSchema[]) => {
    const accountTerm = accountSearch.value.trim().toLowerCase();
    const symbolTerm = symbolSearch.value.trim().toLowerCase();

    // Fast path: no filters
    if (accountTerm === "" && symbolTerm === "") return data;

    const hasAccountFilter = accountTerm.length > 0;
    const hasSymbolFilter = symbolTerm.length > 0;

    const result: AccountInfoSchema[] = [];

    for (let i = 0; i < data.length; i++) {
      const row = data[i];

      // Account name filter
      if (
        hasAccountFilter &&
        !row.account_name.toLowerCase().includes(accountTerm)
      ) {
        continue;
      }

      // Symbol filter
      if (!hasSymbolFilter) {
        // Preserve account even if it has no positions when symbol filter is empty
        result.push(row);
        continue;
      }

      const positions = row.positions;
      if (!positions || positions.size === 0) {
        // With symbol filter, accounts without positions are filtered out
        continue;
      }

      // Build filtered positions map without mutating input
      let matched = 0;
      const filteredPositions = new Map<string, PositionSchema>();
      positions.forEach((pos, key) => {
        // Simple includes matching on symbol
        if (pos.symbol.toLowerCase().includes(symbolTerm)) {
          filteredPositions.set(key, pos);
          matched++;
        }
      });

      if (matched === 0) {
        // No matching positions → drop this account
        continue;
      }

      // Return a shallow-cloned row with filtered maps
      result.push({
        ...row,
        positions: filteredPositions
      });
    }

    return result;
  };

  /**
   * Calculates the total balance and PnL from an array of `AccountInfoSchema` rows.
   *
   * @param data Array of `AccountInfoSchema` rows to calculate totals from.
   * @returns An object containing the total balance and PnL.
   */
  const calculateTotals = (data: AccountInfoSchema[]) => {
    const totals = {
      totalBalance: 0,
      totalPnl: 0
    };

    data.forEach(row => {
      totals.totalBalance += row.account.balance;
      totals.totalPnl += row.totalPnl;
    });

    return totals;
  };

  // expand control
  const expandRowKeys = ref<string[]>([]);

  const getRowKey = (row: AccountInfoSchema) => {
    return `${row.gateway_name}-${row.account_id}`;
  };

  const expandAll = (data: AccountInfoSchema[]) => {
    expandRowKeys.value = data.map(row => getRowKey(row));
  };

  const collapseAll = () => {
    expandRowKeys.value = [];
  };

  const onExpandChange = (
    _: AccountInfoSchema,
    expandedRows: AccountInfoSchema[]
  ) => {
    expandRowKeys.value = expandedRows.map(r => getRowKey(r));
  };

  const unpackAggregation = (
    aggregation: Map<string, AccountInfoSchema>
  ): AccountInfoSchema[] => Array.from(aggregation.values());

  return {
    getRowKey,
    expandRowKeys,
    expandAll,
    collapseAll,
    onExpandChange,
    unpackAggregation,
    accountSearch,
    symbolSearch,
    filterTableData,
    calculateTotals,
    accountColumns,
    tableSize
  };
};
